import type { DefineComponent, ExtractPropTypes } from 'vue';

export enum SchemaType {
  NUMBER = 'number',
  INTEGER = 'integer',
  STRING = 'string',
  OBJECT = 'object',
  ARRAY = 'array',
  BOOLEAN = 'boolean',
}

interface SchemaRef {
  $ref: string;
}

export interface Schema {
  type: SchemaType | string;
  const?: any;
  format?: string;

  title?: string;
  default?: any;

  properties?: {
    [key: string]: Schema;
  };
  items?: Schema | Schema[] | SchemaRef;
  uniqueItems?: any;
  dependencies?: {
    [key: string]: string[] | Schema | SchemaRef;
  };
  oneOf?: Schema[];
  anyOf?: Schema[];
  allOf?: Schema[];
  // TODO: uiSchema
  // vjsf?: VueJsonSchemaConfig
  required?: string[];
  enum?: any[];
  enumNames?: any[];
  enumKeyValue?: any[];
  additionalProperties?: any;
  additionalItems?: Schema;

  minLength?: number;
  maxLength?: number;
  minimum?: number;
  maximum?: number;
  multipleOf?: number;
  exclusiveMaximum?: number;
  exclusiveMinimum?: number;
}

export const FiledPropsDefine = {
  schema: {
    type: Object as PropType<Schema>,
    required: true,
  },
  rootSchema: {
    type: Object as PropType<Schema>,
    required: true,
  },
  value: {
    required: true,
  },
  onChange: {
    type: Function as PropType<(v: any) => void>,
    required: true,
  },
} as const;

export type CommonFieldType = DefineComponent<
  ExtractPropTypes<typeof FiledPropsDefine>
>;

export const ArrayItemWrapperDefine = {
  onAdd: {
    type: Function as PropType<(index: number) => void>,
    required: true,
  },
  onDelete: {
    type: Function as PropType<(index: number) => void>,
    required: true,
  },
  onUp: {
    type: Function as PropType<(index: number) => void>,
    required: true,
  },
  onDown: {
    type: Function as PropType<(index: number) => void>,
    required: true,
  },
  index: {
    type: Number,
    required: true,
  },
} as const;

export type ArrayItemWrapperType = DefineComponent<
  ExtractPropTypes<typeof ArrayItemWrapperDefine>
>;

export const CommonWidgetPropsDefine = {
  value: {},
  onChange: {
    type: Function as PropType<(v: any) => void>,
    required: true,
  },
} as const;

export type CommonWidgetDefine = DefineComponent<
  typeof CommonWidgetPropsDefine,
  {},
  {}
>;

export const SelectionWidgetPropsDefine = {
  ...CommonWidgetPropsDefine,
  options: {
    type: Array as PropType<Array<{ key: string; value: any }>>,
    required: true,
  },
} as const;

export type SelectionWidgetDefine = DefineComponent<
  typeof SelectionWidgetPropsDefine,
  {},
  {}
>;

export enum SelectionWidgetNames {
  SelectionWidget = 'SelectionWidget',
}

export enum CommonWidgetNames {
  TextWidget = 'TextWidget',
  NumberWidget = 'NumberWidget',
}

export interface Theme {
  widgets: {
    [SelectionWidgetNames.SelectionWidget]: SelectionWidgetDefine;
    [CommonWidgetNames.TextWidget]: CommonWidgetDefine;
    [CommonWidgetNames.NumberWidget]: CommonWidgetDefine;
  };
}
